﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Point = Microsoft.Xna.Framework.Point;

namespace VikingArcade_v2._0
{
    public abstract class UserInterfaceControl : IDrawable, IAnimated
    {
        #region IDrawable Members

        public virtual IDrawer GetDrawer()
        {
            throw new Exception("Access to virtual method in abstract class");
        }

        #endregion

        #region IAnimated Members

        public IAnimator GetAnimator()
        {
            throw new NotImplementedException();
        }

        #endregion

        private Point position;

        /// <summary>
        /// Pozycja względem rodzica lub bezwzględna w przypadku jego braku.
        /// </summary>
        public Point Position
        {
            get
            {
                return position;
            }
            set
            {
                position = value;
            }
        }

        /// <summary>
        /// Bezwzględna pozycja.
        /// </summary>
        public Point AbsolutePosition
        {
            get
            {
                if (Parent == null)
                {
                    return position;
                }
                else
                {
                    return new Point(Parent.Position.X + position.X, Parent.Position.Y + position.Y);
                }
            }
        }

        public Point Size { get; set; }

        private List<UserInterfaceControl> children;

        public List<UserInterfaceControl> Children { get { return children; } }

        public UserInterfaceControl Parent { get; set; }

        public bool Visible { get; set; }

        public Anchor Anchor { get; set; }

        public UserInterfaceControl()
        {
            children = new List<UserInterfaceControl>();
            Position = new Point(0, 0);
            Size = new Point(100, 100);
            Visible = true;
            Anchor = Anchor.TopLeft;
        }

        public void AddChild(UserInterfaceControl control)
        {
            control.Parent = this;
            children.Add(control);
        }

        public void AdjustLayout(Size oldSize, Size newSize)
        {
            switch (Anchor)
            {
                case Anchor.TopLeft:
                    AdjustX(DimAnchor.Beginning, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Beginning, oldSize.Height, newSize.Height);
                    break;
                case Anchor.TopRight:
                    AdjustX(DimAnchor.End, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Beginning, oldSize.Height, newSize.Height);
                    break;
                case Anchor.BottomLeft:
                    AdjustX(DimAnchor.Beginning, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.End, oldSize.Height, newSize.Height);
                    break;
                case Anchor.BottomRight:
                    AdjustX(DimAnchor.End, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.End, oldSize.Height, newSize.Height);
                    break;
                case Anchor.Left:
                    AdjustX(DimAnchor.Beginning, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Stretch, oldSize.Height, newSize.Height);
                    break;
                case Anchor.Top:
                    AdjustX(DimAnchor.Stretch, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Beginning, oldSize.Height, newSize.Height);
                    break;
                case Anchor.Right:
                    AdjustX(DimAnchor.End, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Stretch, oldSize.Height, newSize.Height);
                    break;
                case Anchor.Down:
                    AdjustX(DimAnchor.Stretch, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.End, oldSize.Height, newSize.Height);
                    break;
                case Anchor.Stretch:
                    AdjustX(DimAnchor.Stretch, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Stretch, oldSize.Height, newSize.Height);
                    break;
                case Anchor.StretchWidth:
                    AdjustX(DimAnchor.Stretch, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Middle, oldSize.Height, newSize.Height, (float)newSize.Width / (float) oldSize.Width);
                    break;
                case Anchor.StretchHeight:
                    AdjustX(DimAnchor.Middle, oldSize.Width, newSize.Width);
                    AdjustY(DimAnchor.Stretch, oldSize.Height, newSize.Height, (float)newSize.Height / (float) oldSize.Height);
                    break;

            }
            foreach (UserInterfaceControl child in children)
            {
                child.AdjustLayout(oldSize, newSize);
            }
        }

        private void AdjustX(DimAnchor anchor, int oldX, int newX, float? ratio = null)
        {
            if (ratio == null)
            {
                ratio = (float)newX / (float)oldX;
            }
            switch (anchor)
            {
                case DimAnchor.Beginning:
                    break;
                case DimAnchor.Stretch:
                    Position = new Point(Convert.ToInt32(Position.X * ratio), Position.Y);
                    goto case DimAnchor.StretchSize;
                case DimAnchor.StretchSize:
                    Size = new Point(Convert.ToInt32(Size.X * ratio), Size.Y);
                    break;
                case DimAnchor.End:
                    int posR = oldX - Position.X;
                    Position = new Point(newX - posR, Position.Y);
                    break;
                case DimAnchor.Middle:
                    int posM = Position.X - oldX/2;
                    Position = new Point(Convert.ToInt32(newX / 2 + posM * ratio), Position.Y);
                    goto case DimAnchor.StretchSize;
            }
        }

        private void AdjustY(DimAnchor anchor, int oldY, int newY, float? ratio = null)
        {
            if (ratio == null)
            {
                ratio = (float)newY / (float)oldY;
            }
            switch (anchor)
            {
                case DimAnchor.Beginning:
                    break;
                case DimAnchor.Stretch:
                    Position = new Point(Position.X, Convert.ToInt32(Position.Y * ratio));
                    break;
                case DimAnchor.StretchSize:
                    Size = new Point(Size.X, Convert.ToInt32(Size.Y * ratio));
                    break;
                case DimAnchor.End:
                    int posR = oldY - Position.Y;
                    Position = new Point(Position.X, newY - posR);
                    break;
                case DimAnchor.Middle:
                    int posM = Position.Y - oldY / 2;
                    Position = new Point(Position.X, Convert.ToInt32(newY / 2 + posM * ratio));
                    goto case DimAnchor.StretchSize;
            }
        }

        private enum DimAnchor
        {
            Beginning,
            Stretch,
            StretchSize,
            Middle,
            End,
        }

        public virtual void UpdateMouseInput(Point mousePosition, bool leftClicked, bool rightClicked)
        {
            
        }
    }
}
